﻿using Reflexive.IO;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Messaging;
using System.Text;
using System.Threading.Tasks;

namespace Reflexive.IO
{
    public partial class MSMQWriter<T> : IObserver<T>, IDisposable where T : IComparable<T>
    {
        public string _queueName;

        public StatusCode Status
        {
            get;
            private set;
        }

        public MSMQWriter(string queueName)
        {
            _queueName = queueName;
        }

        public void Stop()
        {
            Status = StatusCode.Suspended;
        }

        public void Start()
        {
            if (Status == StatusCode.Completed)
            {
                throw new NotSupportedException("Writer is in the Completed state.");
            }

            Status = StatusCode.Started;
        }

        private void QueueEvent(T TEvent)
        {
            MessageQueueTransaction msgTx = new MessageQueueTransaction();
            try
            {
                
                using (MessageQueue mq = new MessageQueue(_queueName))
                {
                    T message = TEvent;
                    System.Messaging.Message mqMessage = new System.Messaging.Message();
                    mq.Formatter = new System.Messaging.XmlMessageFormatter(new Type[] { typeof(T) });
                    mqMessage.Body = message;
                    mqMessage.Label = Guid.NewGuid().ToString("d");
                    msgTx.Begin();
                    mq.Send(mqMessage, msgTx);
                    msgTx.Commit();
                    mq.Close();
                }
            }
            catch(Exception e)
            {
                msgTx.Abort();
                System.Diagnostics.Trace.TraceError(e.ToString());
            }
        }

        public void OnCompleted()
        {
            Status = StatusCode.Completed;
        }

        public void OnError(Exception error)
        {
            System.Diagnostics.Trace.TraceError(error.ToString());
        }

        public void OnNext(T value)
        {
            if (Status == StatusCode.Started)
            {
                QueueEvent(value);
            }
        }

        public void Dispose()
        {
            OnCompleted();
        }
    }
}
